<?php

namespace Xin\WorkmanServer;

use GatewayWorker\BusinessWorker;
use GatewayWorker\Gateway;
use GatewayWorker\Register;

class WebsocketServer extends Server
{

    /**
     * @var Gateway
     */
    protected $gateway;

    /**
     * @var BusinessWorker
     */
    protected $businessWorker;

    /**
     * @var Register
     */
    protected $register;

    /**
     * @inerhitDoc
     */
    public function run()
    {
        $this->initGatewayServer();
        $this->initBusinessWorkerServer();
        $this->initRegisterServer();
    }

    /**
     * 启动服务网关
     * @return Gateway
     */
    protected function initGatewayServer()
    {
        if (!$this->gateway) {
            $config = $this->getConfig('gateway', []);
            $bindAddress = $this->resolveBindAddress($config);
            $socketName = "websocket://" . $bindAddress;
            $context = $this->resolveContext($config);

            $this->gateway = tap(new Gateway($socketName, $context), function ($gateway) use ($config) {
                WorkerUtil::bindConfig($gateway, $config);
            });
        }

        return $this->gateway;
    }

    /**
     * 创建业务网关
     * @return BusinessWorker
     */
    protected function initBusinessWorkerServer()
    {
        if (!$this->businessWorker) {
            $config = $this->getConfig('business_worker', []);
            $context = $this->resolveContext($config);

            $this->businessWorker = tap(new BusinessWorker('', $context), function ($worker) use ($config) {
                WorkerUtil::bindConfig($worker, $config);
            });
        }

        return $this->businessWorker;
    }

    /**
     * 启动服务注册中心
     * @return Register
     */
    protected function initRegisterServer()
    {
        if (!$this->register) {
            $config = $this->getConfig('register', []);
            $bindAddress = $this->resolveBindAddress($config);
            $socketName = 'text://' . $bindAddress;
            $context = $this->resolveContext($config);

            return tap(new Register($socketName, $context), function ($worker) use ($config) {
                WorkerUtil::bindConfig($worker, $config);
            });
        }

        return $this->register;
    }
}
